{
	const {
		app,
		BrowserWindow,
		Menu,
		screen,
		Tray,
		ipcMain,
		shell
	} = require('electron');
	const timefmt = require('time-stamp')
	const fs = require('fs');
	const ini = require('ini');
	const logger = require('electron-log');
	logger.transports.console.level = 'silly';
	let deeplinkingUrl = null;
	const isDev = require('electron-is-dev');
	const path = require('path');
	const renderProcessApi = path.join(__dirname, '/src/assets/js/preloadWindow.js');
	const __catalog = "win";
	const node_Conf = require('conf');
	const node_config = new node_Conf();
	var ____clientName = "chudy_visual";
	const node_config_app = new node_Conf({"configName":____clientName + "_" + isDev});
	let appConfig = {
		"logo": "",
		"appName":"数据上屏",
		"showSuspensionNav": 0,  //0 自动显示隐藏 1 一直显示
		"navbtns": "drag,desktop,first,pause,prev,next",
		"_contentMode":1 // 1 轮播内容 
	};
	let lastUserDisplay = {};
	let runConfig = {}; 
	app.setLoginItemSettings({
		openAtLogin: true, // Boolean 在登录时启动应用
		openAsHidden: true, // Boolean (可选) mac 表示以隐藏的方式启动应用。~~~~
		// path: '', String (可选) Windows - 在登录时启动的可执行文件。默认为 process.execPath.
		// args: [] String Windows - 要传递给可执行文件的命令行参数。默认为空数组。注意用引号将路径换行。
	})

	function setNodeConfig(key,value){
		try {
			node_config.set(key,value);//更新覆蓋配置，從服務器端獲取到的配置
		} catch (error) {
			loginfo(error);
		}
	}
	function getNodeConfig(key){
		try {
			return node_config.get(key) || node_config_app.get(key) || {};//更新覆蓋配置，從服務器端獲取到的配置
		} catch (error) {
			loginfo(error);
		}
		return {};
	}
	// 读取配置
	try {
		var baseDir = __dirname;
		var cfgpath = "";
		if (isDev) {
			baseDir = baseDir.substr(0, baseDir.indexOf(__catalog) + __catalog.length);
			var __baseCfg = ini.parse(fs.readFileSync(baseDir + '/dist/config/ini/cfg.ini', 'utf-8'));
			var runMode = __baseCfg["comm"]["runmode"] || "dev";
			cfgpath = baseDir + '/dist/config/ini/cfg_' + runMode + '.ini';
		} else {
			baseDir = process.resourcesPath;
			cfgpath = baseDir + "/conf/cfg.ini"
		}
		runConfig = ini.parse(fs.readFileSync(cfgpath, 'utf-8'));
		loginfo("runConfig=============" + JSON.stringify(runConfig));
		//覆盖默认配置
		for (const key in runConfig["clientsetup"]) {
			appConfig[key] = runConfig["clientsetup"][key];
		}
		runConfig["isDev"] = isDev;
		setNodeConfig("appConfig", appConfig);
		setNodeConfig("runConfig", runConfig);
	} catch (error) {
		console.error(error);
	}


	let mainWindow
	let opContentWindow
	let viewContentWindow
	let suspensionNavWindow
	let tray = null
	let aboutContentWindow
	let runDebugMode = false
	let lastLoadPageParam = {}
	let task_playContentList = null;


	let suspensionWindowMin = {
		width:200,
		height:100
	}
	let suspensionWindowOpen = {
		width:100,
		height:100
	}

	if (isDev) { } else {
		runDebugMode = false;
	}

	function loginfo(text) {
		// logger.info(text);
	}

	function logwarn(text) {
		logger.warn(text);
	}

	function logerror(text) {
		logger.error(text);
	}
	let allWindows = [];

	
	function showHideSuspensionNavWindow(op) {

		if(appConfig["showSuspensionNav"] == 1 ){
			op["op"]=1;
		}
		if(suspensionNavWindow){
			//如果屏幕发生了切换，首次校正导航条的位置
			// if(isNeedUpdateNavPosition==true){
			// }
		}else{
			createSuspensionNavWindow(op["options"]);
		}
		if(suspensionNavWindow){
			//打开
			if(op["op"]==1){
				const display = getExternalDisplay();
				suspensionNavWindow.setContentSize(suspensionWindowMin.width, suspensionWindowMin.height);
				suspensionNavWindow.setSize(suspensionWindowMin.width, suspensionWindowMin.height);
				// suspensionNavWindow.setPosition(suspensionWindowOpen["iconX"],suspensionWindowOpen["iconY"]);//初始导航图标的位置
				//显示导航按钮时，设置为置顶
				suspensionNavWindow.showInactive();
				suspensionNavWindow.setAlwaysOnTop(true);
				suspensionNavWindow.moveTop();
			}else{
				suspensionNavWindow.hide();
			}
		}
	}

	function sendSuspensionNavWindowEvent(arg){
		//判断当前是轮播还是单屏展示，轮播则操作导航按钮
		if(null == _queueRolling || _queueRolling.length<=1){
			showHideSuspensionNavWindow({"op":0,"options":{}});
			return;
		}
		showHideSuspensionNavWindow(arg);
	}
	function getSuspensionNavPosition(){
		const display = getExternalDisplay();
		const size = display.size;   //获取显示器的宽高
		let h = size.height*0.4 + 100;
		h = size.height - suspensionWindowMin.height ;//- 50; 
		suspensionWindowOpen.width = size.width;//全屏
		suspensionWindowOpen.height = size.height;//全屏
	
	
		var navBtn = appConfig.navbtns;
		var navBtns = [];
		if(undefined !=navBtn &&  null!=navBtn && ""!=navBtn){
			navBtns = navBtn.split(",");
		}
		var width = (navBtns.length+2) * 50 + 20;
		
		suspensionWindowMin.width = width;
	
		suspensionWindowOpen["screenWidth"] = size.width;//变量存储窗口大小，省去每次重新获取
		suspensionWindowOpen["screenHeight"] = size.height;
		suspensionWindowOpen["iconY"] = h;//导航按钮出现的位置
		suspensionWindowOpen["iconX"] = display.bounds.x + size.width - suspensionWindowMin.width-20;
		suspensionWindowOpen["screenType"] = "h";
		if (size.width < size.height) {
			suspensionWindowOpen["screenType"] = "v";
		}
	}
	function createSuspensionNavWindow(options) {
		//创建导航按钮窗口
		//初始化窗口大小和 按钮位置
		getSuspensionNavPosition();
		//全屏窗口
	    suspensionNavWindow = new BrowserWindow({
			id:"appSuspensionNavWindow",
			"x":getExternalDisplay().bounds.x,
			"y":getExternalDisplay().bounds.y,
			width: suspensionWindowMin.width, //悬浮窗口的宽度 比实际DIV的宽度要多2px 因为有1px的边框
		    height: suspensionWindowMin.height, //悬浮窗口的高度 比实际DIV的高度要多2px 因为有1px的边框
	        frame: false,   //要创建无边框窗口
	        resizable: false, //禁止窗口大小缩放
			kiosk :true,
	        show: false, //先不让窗口显示
			focusable :false,
	        webPreferences: {
	            devTools: true, //关闭调试工具
				nodeIntegration: true,
				nodeIntegrationInWorker:true,
				contextIsolation: false
	        },
	        transparent: true,  //设置透明
	        alwaysOnTop: true ,//窗口是否总是显示在其他窗口之前
	    });
		//加载页面
	    suspensionNavWindow.loadURL(`file://${__dirname}/src/page/suspension_nav.html`);
	    suspensionNavWindow.once('ready-to-show', () => {
	//         suspensionNavWindow.show()
	    });

		suspensionNavWindow.setPosition(suspensionWindowOpen["iconX"],suspensionWindowOpen["iconY"]);//初始导航图标的位置
	    suspensionNavWindow.on('close', () => {
	        suspensionNavWindow = null;
	    })
	    suspensionNavWindow.setSkipTaskbar(true);
	//     suspensionNavWindow.webContents.openDevTools()
	}
	
	function createAboutContentWindow() {
		// 创建浏览器窗口。
		if (aboutContentWindow) {
			aboutContentWindow.focus()
		} else {
			aboutContentWindow = new BrowserWindow({
				titleBarStyle: 'customButtonsOnHover',
				frame: true,
				fullscreen: false,
				"webPreferences": {
					nodeIntegration: true
				}
			})
		}
		aboutContentWindow.loadURL(`file://${__dirname}/src/page/about.html`)
		aboutContentWindow.on('closed', () => {
			aboutContentWindow = null
		})
	}
	/**
	 * 创建主窗口
	 */
	function createMainContentWindow() {
		loginfo(__dirname);
		if (mainWindow) {
			mainWindow.loadURL(`file://${__dirname}/src/page/index_s.html`)
			if (runDebugMode == true) {
				// 打开开发者工具
				mainWindow.webContents.openDevTools()
			}
		} else {
			// 创建浏览器窗口。
			mainWindow = new BrowserWindow({
				titleBarStyle: 'customButtonsOnHover',
				frame: false,
				"show": false,
				fullscreen: true,
				webPreferences: {
					nodeIntegration: true,
					nodeIntegrationInWorker:true,
					contextIsolation: false,
					enableRemoteModule:true,
					backgroundThrottling:false,
					preload: path.join(__dirname, 'preload.js')
				}
			})

			mainWindow.setSkipTaskbar(true);
			// 然后加载应用的 index.html。
			//mainWindow.loadFile('index.html')
			mainWindow.loadURL(`file://${__dirname}/src/page/index_s.html`)
			if (runDebugMode == true) {
				// 打开开发者工具
				mainWindow.webContents.openDevTools()
			}
			mainWindow.once('ready-to-show', () => {
				mainWindow.show();
			})
			// 当 window 被关闭，这个事件会被触发。
			mainWindow.on('closed', () => {
				mainWindow = null
			})
			mainWindow.on('close', (event) => {
				mainWindow.hide();
				mainWindow.setSkipTaskbar(true);
				event.preventDefault();
			});

		}
	}


	function restartApp() {
		app.relaunch({
			args: process.argv.slice(1).concat(['--relaunch'])
		})
		app.exit(0);
	}
	function createWindow() {
		createMainContentWindow();
		//接收到 网络在线离线消息时
		ipcMain.on('app-onlinemessage', (event, arg) => {
			logger.info("app-onlinemessage:",arg) // prints "ping"
		})

		//接收到推送的消息时，将消息转发到主页面，主页面对消息做解析，决定显示的内容
		ipcMain.on('app-pushmessage', (event, arg) => {
			loginfo("app-pushmessage:" + arg) // prints "ping"
		})

		//接收到推送的消息时，将消息转发到主页面，主页面对消息做解析，决定显示的内容
		ipcMain.on('app-socket-onlinemessage', (event, arg) => {
			loginfo('app-socket-onlinemessage:' + arg) // prints "ping"
		})

		ipcMain.on('app-changeContentPage', (event, arg) => {
			loginfo("******app-changeContentPage***************=" + arg) // prints "ping"
			changeContentPage({
				'showType': arg
			});
		})
		//触摸页面 3 向左滑动，4向右滑动，0 没滑动
		ipcMain.on('app-touchContentPage', (event, arg) => {
			loginfo("**app-touchContentPage*************=" + JSON.stringify(arg)) // prints "ping"
			//触摸操作时，对播放列表进行操作。
			touchContentPage(arg)
		})
		/**
		 * step0
		 */
		ipcMain.on('app-loadContentPage', (event, arg) => {
			//loginfo(arg) // prints "ping"
			lastLoadPageParam = arg
			lastLoadPageParam['appcfg'] = {
				debug: runDebugMode
			}
			if (lastLoadPageParam["clientsetup"]) {
				try {
					for (const key in lastLoadPageParam["clientsetup"]) {

						appConfig[key] = lastLoadPageParam["clientsetup"][key];
					}
					node_config.set("appConfig", appConfig);//更新覆蓋配置，從服務器端獲取到的配置
				} catch (error) {

				}
			}
			loadContentPage(arg)
		})

		ipcMain.on('app-clientEvent', (event, arg) => {
			//loginfo(arg);
			if (arg["data"]["eventkey"] == "RESTARTAPP") {
				restartApp();
			}
		})

		ipcMain.on('app-suspensionWindowEvent', (event, arg) => {
			loginfo(arg);//showHideSuspensionWindow
			if(arg["type"] == "show"){
				//显示导航窗口
				// showHideSuspensionWindow(arg);
			}else if(arg["type"] == "resize"){
				// resizeSuspensionWindow(arg);
			}else if(arg["type"] == "getScreens"){
				arg["screens"] = _contentlist;
				suspensionWindow.webContents.send('app-suspensionWindowEvent', arg)
			}else if(arg["type"] == "play"){
				var id = arg["screenId"]
				touchContentPage(arg);
			}else if(arg["type"] == "opNavWindow"){
				// showHideSuspensionWindow(arg);
				
			}else if(arg["type"] == "goToPrev"){
				
				//上一屏幕 3 
				var p = {
					"delayed": 30,
					"direction":  4
				};

				touchContentPage(p);
				
			}else if(arg["type"] == "goToNext"){
				//下一屏幕 3 
				var p = {
					"delayed": 30,
					"direction": 3
				};
				
				touchContentPage(p);
				
			}else if(arg["type"] == "goToFirst"){
				
				if(null!= _contentlist && _contentlist.length>0)
				{
					var p = {
						"type": "play",
						"screenId": _contentlist[0].id,
						"delayed": 30,
						"direction": -4
					};
					
					
					touchContentPage(p);
					if(task_playContentList){

					}else{
						task_playContentList = setInterval(playContentList, 1000);
					}
					
					//隐藏九宫格导航窗口
					// if (suspensionWindow) {
					// 	suspensionWindow.showInactive();
					// }

				}

			}else if(arg["type"] == "goToDeskTop"){

				//暂停轮播，关闭轮播窗口
				pauseAllRollingScreens();
				//隐藏主窗口
				if (mainWindow) {
					mainWindow.hide();
				}
				//隐藏九宫格导航窗口
				// if (suspensionWindow) {
				// 	suspensionWindow.setAlwaysOnTop(false);
				// 	suspensionWindow.hide();
				// }
			}else if(arg["type"] == "goToExitClient"){
				app.exit(0);
			}else if(arg["type"] == "goToAutoPlay"){
				//开启定时器，开始自动轮播
				loginfo("goToAutoPlay 开启定时器 = " + task_playContentList);
				if(task_playContentList){
				}else{
					task_playContentList = setInterval(playContentList, 1000);
				}
			}else if(arg["type"] == "goToPause"){
				//关闭定时器，暂停轮播
				loginfo("goToPause定时器关闭 = " + task_playContentList);
				if (task_playContentList) {
					clearInterval(task_playContentList);
					task_playContentList = null;
				}
			}else if(arg["type"] == "minMain"){
				mainWindow.hide();
			}else if(arg["type"] == "openPage"){
				shell.openExternal(arg["url"]);
			}
		})

		
		ipcMain.on('app-checkUpdate', (event, arg) => {
			loginfo("app-checkUpdate") // prints "ping"
			arg = JSON.parse(arg);
			autoHotUpdateApp(arg).then(function (data) {
				loginfo(data);
			}, function (reason, data) {
				loginfo('rejected');
				loginfo(reason);
			})
		})

		if (isDev) {
			loginfo(['Running in development','demo']);
			//开发环境
		} else {
			//运行环境，检查更新
			loginfo('Running in production');
			//檢查注冊表信息，加入开机自动启动
			createClientReg();
		}

	}
	function createTray() {
		//系统托盘图标目录
		trayIcon = path.join(__dirname, ''); //app是选取的目录
		tray = new Tray(path.join(trayIcon, 'app.ico')); //app.ico是app目录下的ico文件
		//托盘右击菜单
		const contextMenu = Menu.buildFromTemplate([{
			label: '调试模式打开',
			click() {
				//关闭除主窗口之外的窗口，并重新打开
				lastLoadPageParam['app'] = {
					debug: true
				}
				runDebugMode = true;
				createMainContentWindow()
				loadContentPage(lastLoadPageParam)
			}
		}, {
			label: '重启应用',
			click() {
				restartApp();
			}
		}
		, {
			label: '强制退出',
			click() {
				app.exit(0)
			}
		}])
		tray.setToolTip("数据上屏");
		tray.setContextMenu(contextMenu)
		tray.on('click', () => {
			if (mainWindow.isVisible()) {
				mainWindow.hide();
				mainWindow.setSkipTaskbar(true);
				clickTraySuspension(false);
			} else {
				mainWindow.show();
				mainWindow.setSkipTaskbar(true);
				clickTraySuspension();
			}
		})

	}
	const regedit = require('regedit');
	regedit.setExternalVBSLocation('./resources/vbs');

	let regKey = "ChudyVisualClient";
	function createClientReg() {
		//注册表检查
		// 开机自启动
		// 查看开机自启注册表是否已经注册 regKey
		regedit.list('HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run', (err, data) => {
			if (err) {
				logger.info(err)
			} else if (!data['HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run'].values[regKey] || data['HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run'].values[regKey] !== app.getPath('exe')) {
				// 未注册或注册地址与现地址不一致则 进行注册
				var regInfo = {};
				regInfo[regKey] = {
					value: app.getPath('exe'),
					type: 'REG_SZ'
				};
				regedit.putValue({
					'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run': regInfo
				}, (error) => {
					if (error) logger.info(error)
				})
			}
		});
	}
	let appWebServer = null;
	let appWsServer = null;
	var get_client_ip = function(req) {
		var ip = req.headers['x-forwarded-for'] || req.ip || req.connection.remoteAddress ||
		req.socket.remoteAddress || '';
		// console.log("req.headers['x-forwarded-for']",req.headers['x-forwarded-for']);
		// console.log("req.ip",req.ip);
		// console.log("req.connection.remoteAddress",req.connection.remoteAddress);
		// console.log("req.socket.remoteAddress",req.socket.remoteAddress);
		
		if(ip.split(',').length>0){	
			ip = ip.split(',')[0]	
		}
		return ip;
	};
	const os = require('os');
	function getIPAdress() {
		var interfaces = os.networkInterfaces();
		for (var devName in interfaces) {
			var iface = interfaces[devName];
			for (var i = 0; i < iface.length; i++) {
				var alias = iface[i];
				if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
					return alias.address;
				}
			}
		}
	}

	function createWebServer(){
		const express = require('express');
		const expressWs = require('express-ws');
		const bodyParser = require('body-parser')
		const webapp = express();
		const expWs = expressWs(webapp);
		webapp.use(bodyParser.json());
		webapp.use(bodyParser.urlencoded({extended: false}));
		webapp.use(express.static(__dirname+'/public', {}))
		// webapp.use(bodyParser);
		// webapp.all('/', function (req, res, next) {
		// 	res.writeHead(200,{
		// 		'content-type':'text/html;charset=utf8'
		// 	})
		// 	res.end('欢迎使用触达云屏！');
		// })
		function checkToken(req){
			let token = req.headers["token"];
			if(!token){
				token = req.query["token"];
			}
			let timestimep = req.headers["timestimep"];
			if(!timestimep){
				timestimep = req.query["timestimep"];
			}

			if(token === runConfig["comm"]["apptoken"]){
				return true;
			}
			return false;
		}
		webapp.ws('/', function (ws, req) {
			console.log('connect success',req.query)
			ws["deviceid"] = req.query["deviceid"]
			ws["deviceip"] = req.query["deviceip"]
			console.log(ws["deviceid"])
			// 使用 ws 的 send 方法向连接另一端的客户端发送数据
			ws.send('{"default":"connect to server with WebSocket success"}')
			// 使用 on 方法监听事件
			//   message 事件表示从另一段（服务端）传入的数据
			ws.on('message', function (msg) {
				//console.log(`receive message ${msg}`)
				// ws.send('{"default":"' + msg + '"}')
			})
			
			// 设置定时发送消息
			// let timer = setInterval(() => {
			// 	ws.send(`interval message ${new Date()}`)
			// }, 2000)
			
			// close 事件表示客户端断开连接时执行的回调函数
			ws.on('close', function (e) {
				console.log('close connection')
				// clearInterval(timer)
				// timer = undefined
			})
		})
		var webappWs = expWs.getWss('/');
		webapp.all('/push', function (req, res, next) {
			res.writeHead(200,{
				'content-type':'text/html;charset=utf8'
			})
			let rsp =null;
			if(checkToken(req)){
				const deviceid = req.query["deviceid"];
				const deviceids = req.query["deviceids"];
				const deviceip = req.query["ip"];
				const deviceips = req.query["ips"];
				
				 
				webappWs.clients.forEach(function (client) {
					
					var msg = {"pushtype":"screens","contentlist": req.body};
					msg = JSON.stringify(msg);
					// client.send(JSON.stringify(msg));
					// if (client.readyState === WebSocket.OPEN) {
					// 	client.send('{"pushtype":"screens","contentlist":' + req.body +'}');
					// }
					//判断参数
					if(deviceid && deviceid.length>0){
						if(deviceid == client["deviceid"]){
							client.send(msg);
						}
					}else if(deviceids && deviceids.length>0){
						let devids = "," + deviceids + ",";
						if(devids.indexOf(client["deviceid"]) >=0){
							client.send(msg);
						}
					}else if(deviceip && deviceip.length>0){
						if(deviceip == client["deviceip"]){
							client.send(msg);
						}
					}else if(deviceips && deviceips.length>0){
						let devids = "," + deviceips + ",";
						if(devids.indexOf(client["deviceip"]) >=0){
							client.send(msg);
						}
					}
				});
				rsp = {"code":"0","data":[]};
			}else{
				rsp = {"code":"1","data":[],"msg":"非法访问"};
			}
			
			res.end(JSON.stringify(rsp));
		})
		webapp.all('/client/devicelist', function (req, res, next) {
			res.writeHead(200,{
				'content-type':'application/json;charset=utf8'
			})
			var data = [];
			webappWs.clients.forEach(function (client) {
				data.push({
					"deviceid":client["deviceid"],
					"deviceip":client["deviceip"]
				});
			});

			var rsp = {"code":"0","data":data};
			res.end(JSON.stringify(rsp));
		})
		webapp.all('/client/getClientInfo', function (req, res, next) {
			let locIp = getIPAdress();
			res.writeHead(200,{
				'content-type':'application/json;charset=utf8'
			})
			console.log("getClientInfo postparams",req.params);
			var data = {
				"device":{
					"ip":locIp,
					"id":req.body["deviceid"]
				},
				"contentlist":[] //last getlist
			};

			var rsp = {"code":"0","data":data,"isServer":true};
			res.end(JSON.stringify(rsp));
		})

		webapp.all('/client/displays', function (req, res, next) {
			res.writeHead(200,{
				'content-type':'application/json;charset=utf8'
			})
			var rsp = {"code":"0","data":getAllDisplay()};
			res.end(JSON.stringify(rsp));
		})
		
		const port = 25004;
		webapp.listen(runConfig["ws"]["ws_port"], () => {console.log(`express server listen at http://localhost:${runConfig["ws"]["ws_port"]}`)})
	}
	
	function getExternalDisplay(){
		let displays = screen.getAllDisplays();
		let userDisplay = getNodeConfig("userDisplay");
		let displayId = "";
		if(userDisplay && userDisplay["default"]){
			displayId = userDisplay["default"];
		}
		let externalDisplay = displays.find((display) => {
		　　return display.id == displayId;
	　　 })
		let cDisplay = {};
		if(externalDisplay){
			cDisplay = externalDisplay;
		}else{
			cDisplay = screen.getPrimaryDisplay();
		}
		if(lastUserDisplay.id != cDisplay.id){
			lastUserDisplay = cDisplay;
			//切换屏幕后，更新导航条的位置
			getSuspensionNavPosition();
			if(suspensionNavWindow){
				suspensionNavWindow.setPosition(suspensionWindowOpen["iconX"],suspensionWindowOpen["iconY"]);//初始导航图标的位置
			}
		}
		return cDisplay;
	}
	function getAllDisplay(){
		let displays = screen.getAllDisplays();
		let displayList = [];
		displays.forEach((d)=>{
			displayList.push({
				id:d.id,
				bounds:d.bounds,
				internal:d.internal,
				size:d.size
			});
		});	
		/**
		 * id,
		 *  bounds: { x: 0, y: 0, width: 1920, height: 1080 },
    workArea: { x: 0, y: 0, width: 1920, height: 1040 },
			internal,
			size: { width: 2048, height: 1152 },
		 */
// 　　	 let externalDisplay = displays.find((display) => {
// 		　　return display.bounds.x !== 0 || display.bounds.y !== 0
// 	　　 })
// 		console.log("externalDisplay",externalDisplay);
		// console.log("displayList",displayList);
		return displayList;
	}
	function appReady() {
		//读取用户配置显示到哪个显示器，未读取到，则显示到默认显示器

		//如果读取到的显示器ID，不在当前显示器范围内，也显示到默认显示器。
		screen.on('display-added', (event, newDisplay ) => {
			console.log("add",event,newDisplay);
		});
		screen.on('display-removed', (event, oldDisplay  ) => {
			console.log("removed",event,oldDisplay );
		});
		

		app.commandLine.appendSwitch('autoplay-policy', 'no-user-gesture-required'); //设置允许自动播放音乐
		loginfo(process.argv);
		const gotTheLock = app.requestSingleInstanceLock();
		if (!gotTheLock) {
			app.quit();
			return;
		} else {
			app.on('second-instance', (event, commandLine, workingDirectory) => {
				if (process.platform == 'win32') {
					// Keep only command line / deep linked arguments
					deeplinkingUrl = commandLine.slice(1);
					logger.info("second-instance 333333333333333333333333333333333" + deeplinkingUrl);
				}
				// 当运行第二个实例时,如果应用此时在桌面，则唤醒应用
			})

			createWindow();
			createTray();
			createWebServer();
		}
	}
	// 创建浏览器窗口时，调用这个函数。
	// 部分 API 在 ready 事件触发后才能使用。
	app.on('ready', appReady)

	// app.whenReady().then(() => {
	// 	createWindow()
		
	// 	app.on('activate', () => {
	// 		if (BrowserWindow.getAllWindows().length === 0) {
	// 		createWindow()
	// 		}
	// 	})
	// })

	app.allowRendererProcessReuse = false;
	app.setUserTasks([]);
	// 当全部窗口关闭时退出。
	app.on('window-all-closed', () => {
		// 在 macOS 上，除非用户用 Cmd + Q 确定地退出，
		// 否则绝大部分应用及其菜单栏会保持激活。
		if (process.platform !== 'darwin') {
			//app.quit()
		}
	})

	app.on('activate', () => {
		// 在macOS上，当单击dock图标并且没有其他窗口打开时，
		// 通常在应用程序中重新创建一个窗口。
		if (mainWindow === null) {
			createWindow()
		}
	})

	//注册通过url调起应用 regKey://
	// if (!app.isDefaultProtocolClient(regKey)) {
	// 	if (app.isPackaged) {
	// 		app.setAsDefaultProtocolClient(regKey);
	// 	}
	// }
	app.on('web-contents-created', (event, contents) => {
		contents.setWindowOpenHandler(({url , frameName,features , disposition,referrer,postBody }) => {
			// In this example, we'll ask the operating system
			// to open this event's url in the default browser.
			//event.preventDefault()
			loginfo("new-window navigationUrl=" + url + ",frameName=" + frameName + ",disposition=" + disposition);
			//shell.openExternal(navigationUrl)
			// console.log("new-window",options);
			let overrideBrowserWindowOptions = {"menuBarVisible":false,"autoHideMenuBar":true};
			return {action: 'allow', overrideBrowserWindowOptions};
		})
	})

	app.on('will-finish-launching', function () {
		// Protocol handler for osx
		app.on('open-url', function (event, url) {
			event.preventDefault()
			deeplinkingUrl = url;
			loginfo("will-finish-launching open-url " + deeplinkingUrl);
		})
	})
	//改变窗口的显示隐藏，操作窗口和 无操作窗口
	function changeContentPage(msg) {
		if (!msg['showType']) {
			msg['showType'] = 'op';
		}
		if (msg['showType'] == 'op') {
			//通过reload 重新加载，实现重新开始计时
			//opContentWindow.reload();

			if (opContentWindow) {
				opContentWindow.show();
				//通过发消息给页面，触发重新计时
				opContentWindow.webContents.send('app-opWindowShow', msg)
				//loginfo('opContentWindow-show');
				viewContentWindow.hide();
				//loginfo('viewContentWindow-hide');
			} else {
				loginfo('viewContentWindow-hide + opContentWindow is null');
			}

		} else {
			loginfo('opContentWindow1-hide');
			//最后加载的数据
			loginfo(["lastLoadPageParam",lastLoadPageParam]);
			if (lastLoadPageParam['pushtype'] == 'screen') {
				if (lastLoadPageParam['data']['viewurl']) {
					if (opContentWindow) {
						opContentWindow.hide();
					}

					//loginfo('opContentWindow1-hide');
					if (viewContentWindow) {
						viewContentWindow.show();
					}
					//loginfo('viewContentWindow1-show');
				}
			}

		}
	}

	//定时窗口对象
	var cScreenObjFixedtime = {
		"index": 0,
		"playtime": 0,
		"starttime": 0,
		"duration": 60,
		"durationDefault": 60,
		"winid": ""
	};
	//普通窗口对象
	var cScreenObj = {
		"index": 0,
		"playtime": 0,
		"starttime": 0,
		"duration": 60,
		"durationDefault": 60
	}; 
	//创建多个轮播窗口//默认从头开始
	var _contentlist = []; //要展示的内容集合
	
	var _queueFixedtime = {}; //队列，定时内容,时间作为key，内容作为value
	let _queueRolling = []; //队列，滚动展示内容
	let _contentWindows = {}; //节目单对应的展示窗口对象集合

	//根据内容id，获取内容对象
	function getContentScreenById(id) {
		loginfo("getContentScreenById = " + id);
		var contentScreen = null;
		for (let c of _contentlist) {
			let winid = "window_" + c.id;
			if (winid == id) {
				contentScreen = c;
				break;
			}
		}
		return contentScreen;
	}

	/**
	 * 给内容列表，添加截屏图片 
	 * @param {*} winid 
	 * @param {*} obj 
	 */
	function setContentScreenAttrByWinId(winid, obj) {
		loginfo("setContentScreenAttrByWinId = " + winid);
		var contentScreen = null;
		for (let c of _contentlist) {
			let t_winid = "window_" + c.id;
			if (t_winid == winid) {
				//设置属性
				for (let attr in obj) {
					c[attr] = obj[attr];
				}
				break;
			}
		}
	}
	//关闭不需要的内容窗口
	function closeScreensByIds() {
		var contentIds = ","
		for (var i = 0; i < _contentlist.length; i++) {
			let c = _contentlist[i];
			let winid = "window_" + c.id;
			contentIds += winid + ",";
		}
		loginfo("for = contentIds = " + contentIds);
		for (let winid in _contentWindows) {
			if (contentIds.indexOf("," + winid + ",") < 0) {
				loginfo("关闭窗口winid = " + winid);
				if (_contentWindows[winid]) {
					_contentWindows[winid].destroy();
				}
			}
		}
	}

	/**
	 * 
	 */
	function closeAllRollingScreens() {
		//关闭窗口
		for (let winid in _contentWindows) {
			loginfo("closeAllRollingScreens关闭窗口winid = " + winid);
			if (_contentWindows[winid]) {
				_contentWindows[winid].destroy();
			}
		}
		//清空轮播列表
		// _contentlist = new Array();
		_contentWindows = {};
		_queueFixedtime = {};
		_queueRolling = new Array();
		//关闭定时器
		loginfo("closeAllRollingScreens定时器关闭 = " + task_playContentList);
		stopPlayContentListTask();
	}

	/**
	 * 暂停轮播
	 */
	function pauseAllRollingScreens() {
		//全部静音
		setAudioMutedAllScreen();
		//全部隐藏
		hiddenAllScreen();
		//关闭定时器，暂停轮播
		loginfo("closeAllRollingScreens定时器关闭 = " + task_playContentList);
		stopPlayContentListTask();
	}

	/**
	 * 开始轮播
	 */
	function playAllRollingScreens() {
		startPlay(0);
		//秒级定时任务，检查需要定时播放的内容，对于定时需要播放的，到时间直接切换
		startPlayContentListTask();
	}

	/**
	 * 停止轮播任务，清除定时器
	 */
	function stopPlayContentListTask(){
		if (task_playContentList) {
			clearInterval(task_playContentList);
			task_playContentList = null;
		}
	}
	/**
	 * 开始轮播任务，设置定时器
	 */
	function startPlayContentListTask(){
		if (task_playContentList) {
		} else {
			task_playContentList = setInterval(playContentList, 1000);
		}
	}

	/**
	 * step2
	 * 创建轮播窗口
	 * @param {*} msg 
	 */
	function createScreens(msg) {
		_contentlist = msg["contentlist"] || [];//内容列表
		loginfo("_contentlist = " + _contentlist.length)

		var cDisplay = getExternalDisplay();
		var options = {
			"titleBarStyle": "customButtonsOnHover",
			"x":cDisplay.bounds.x,
			"y":cDisplay.bounds.y,
			"frame": false,
			"fullscreen": true,
			// "parent": mainWindow,
			focusable:false,
			"modal": true,
			"show": false,
			kiosk:true,
			"webPreferences": {
				nodeIntegration: true,
				preload: renderProcessApi
			}
		}
		var defaultAudioMuted = true;//静音
		if((_contentlist || []).length<=1){
			options.focusable=true;
			options.parent = mainWindow;
			defaultAudioMuted = false;

			//close all
			closeAllRollingScreens();
		}
		_queueRolling = new Array();//轮播列表
		for (var i = 0; i < _contentlist.length; i++) {
			let c = _contentlist[i];
			let winid = "window_" + c.id;
			options["title"] = c.title || appConfig.appName;

			if (!_contentWindows[winid]) {
				_contentWindows[winid] = new BrowserWindow(options)
				_contentWindows[winid].setSkipTaskbar(true);
				// _contentWindows[winid].setBackgroundColor('#171b22');
			}
			_contentWindows[winid].setBounds({
				"x":cDisplay.bounds.x,
				"y":cDisplay.bounds.y
			});
			
			_contentWindows[winid].webContents.setAudioMuted(defaultAudioMuted);//静音
			if (c && c.url) {
				_contentWindows[winid].loadURL(c.url)
			}
			// 当 window 被关闭，这个事件会被触发。
			_contentWindows[winid].on('closed', () => {
				_contentWindows[winid] = null
			})
			_contentWindows[winid].once('ready-to-show', () => {
				_contentWindows[winid].show()
				//可以截屏
			})

			if ((null != c.starttime && "" != c.starttime) || (null != c.startdate && "" != c.startdate)) {
				//定时的内容
				loginfo("***************" + timefmt('YYYY-MM-DD'));
				if (null == c.starttime || "" == c.starttime) {
					//时间为空，则表示无需定时，加入轮播队列
					_queueRolling.push(winid);
				} else {
					if (null == c.startdate || "" == c.startdate) {
						_queueFixedtime[c.starttime] = winid;
					} else {
						_queueFixedtime[c.startdate + " " + c.starttime] = winid;
					}
				}

			} else {
				_queueRolling.push(winid);
			}
		}
		closeScreensByIds(); //关闭不需要展示的内容窗口
		startPlay(0);//开始播放第一个大屏
		//秒级定时任务，检查需要定时播放的内容，对于定时需要播放的，到时间直接切换
		//console.log("startPlayContent",_contentlist.length);
		if(_contentlist.length>1){
			startPlayContentListTask();
		}
	}

	/**
	 * 
	 * @param {截屏}} winid 
	 * @param {*} maxWidth 
	 */
	function captureWindowPage(winid, maxWidth) {
		maxWidth = maxWidth || 120;
		//loginfo("**************************************************" + winid);
		if (_contentWindows[winid]) {
			_contentWindows[winid].capturePage().then((image) => {
				var aspectRatio = image.getAspectRatio();
				loginfo("### captureWindowPage _contentWindows ## image.getAspectRatio()***" + aspectRatio);
				var ops = { "quality": "good" };
				if (aspectRatio >= 1) {
					ops["width"] = maxWidth;
				} else {
					ops["height"] = maxWidth;
				}
				var newimg = image.resize(ops);
				setContentScreenAttrByWinId(winid, { "_capture": newimg.toDataURL() })
			})
				.catch((err) => console.log(err));

		}
	}

	//设置全部大屏为静音
	function setAudioMutedAllScreen(flag) {
		for (let i of _queueRolling) {
			if (_contentWindows[i]) {
				_contentWindows[i].webContents.setAudioMuted(true) //静音
			}
		}

		for (let i in _queueFixedtime) {
			if (_contentWindows[i]) {
				//_contentWindows[i].hide();
				_contentWindows[i].webContents.setAudioMuted(true) //静音
				//_contentWindows[i].setAlwaysOnTop(false);
			}
		}
	}
	//隱藏全部大屏为静音
	function hiddenAllScreen(flag) {
		for (let i of _queueRolling) {
			if (_contentWindows[i]) {
				//_contentWindows[i].webContents.setAudioMuted(true) //静音
				_contentWindows[i].hide();
			}
		}

		for (let i in _queueFixedtime) {
			if (_contentWindows[i]) {
				_contentWindows[i].hide();
				//_contentWindows[i].webContents.setAudioMuted(true) //静音
				//_contentWindows[i].setAlwaysOnTop(false);
			}
		}
	}

	function clickTraySuspension(show = true){
		if (true === show && suspensionNavWindow) {
			//有轮播列表时，显示导航条 _queueRolling
			if(_queueRolling && _queueRolling.length>1){
				suspensionNavWindow.show();
				suspensionNavWindow.moveTop();
			}else{
				suspensionNavWindow.hide();
			}
		} 

		if(!show && suspensionNavWindow){
			suspensionNavWindow.hide();
		}
	}

	function startPlay(index) {

		loginfo("开始播放的索引=" + index)
		if (_queueRolling.length <= 0) {
			//无播放列表
			loginfo("无播放列表")
			return;
		}

		setAudioMutedAllScreen();

		let winid = _queueRolling[index];
		let contentScreen = getContentScreenById(winid);
		startPlayByWinid(winid);
		cScreenObj.index = index;
		cScreenObj.winid = winid;
		cScreenObj.playtime = 0; //秒
		cScreenObj.starttime = new Date().getTime(); //毫秒
		cScreenObj.duration = contentScreen["duration"] || cScreenObj["durationDefault"];
		loginfo("正在播放============" + JSON.stringify(cScreenObj))
	}

	function startPlayRolling(winid) {

		setAudioMutedAllScreen();
		let contentScreen = getContentScreenById(winid);
		startPlayByWinid(winid);
		cScreenObjFixedtime.winid = winid;
		cScreenObjFixedtime.playtime = 0; //秒
		cScreenObjFixedtime.starttime = new Date().getTime(); //毫秒
		cScreenObjFixedtime.duration = contentScreen["duration"] || cScreenObjFixedtime["durationDefault"];
	}
	function startPlayByWinid(winid) {
		// console.log("startPlayByWinid",winid);
		let contentScreen = getContentScreenById(winid);
		if (null == contentScreen) {
			return;
		}
		if (_contentWindows[winid]) {
			_contentWindows[winid].webContents.setAudioMuted(false);
			// console.log("切换播放开始",winid);
			// _contentWindows[winid].show();
			_contentWindows[winid].moveTop();
			_contentWindows[winid].show();
			// _contentWindows[winid].isAlwaysOnTop(true);
			if (runDebugMode == true) {
				// 打开开发者工具
				_contentWindows[winid].webContents.openDevTools()
			}
		} else {
			var options = {
				"titleBarStyle": "customButtonsOnHover",
				"x":lastUserDisplay.bounds.x,
				"y":lastUserDisplay.bounds.y,
				"frame": false,
				"fullscreen": true,
				// "parent": mainWindow,
				focusable:false,
				"modal": true,
				"show": false,
				kiosk:true,
				"webPreferences": {
					nodeIntegration: true,
					preload: renderProcessApi
				}
			}
			var defaultAudioMuted = true;//静音
			if((_contentlist || []).length<=1){
				options.focusable=true;
				options.parent = mainWindow;
				defaultAudioMuted = false;
				if(mainWindow){
					mainWindow.show();
					mainWindow.focus();
				}
			}
			//loginfo(contentScreen);
			_contentWindows[winid] = new BrowserWindow(options)
			_contentWindows[winid].webContents.setAudioMuted(defaultAudioMuted)
			_contentWindows[winid].loadURL(contentScreen.url)
			// 当 window 被关闭，这个事件会被触发。
			_contentWindows[winid].on('closed', () => {
				_contentWindows[winid] = null
			})
			_contentWindows[winid].once('ready-to-show', () => {
				_contentWindows[winid].moveTop();
				_contentWindows[winid].show();
				_contentWindows[winid].focus();
				//_contentWindows[winid].isAlwaysOnTop(true);
				_contentWindows[winid].webContents.setAudioMuted(false);
				
			})
			//_contentWindows[winid].setAlwaysOnTop(true);
			if (runDebugMode == true) {
				// 打开开发者工具
				_contentWindows[winid].webContents.openDevTools()
			}
		}

		cScreenObj.winid = winid;
	}


	//触摸页面 3 向左滑动，4向右滑动，0 没滑动
	function touchContentPage(msg) {
		loginfo("touchContentPage=触发了",msg)

		var delayed = msg['delayed'] || 30;//单位秒
		cScreenObj.playtime = 0; //秒
		cScreenObj.starttime = new Date().getTime(); //毫秒
		if (msg['direction'] == 3) {
			//用户在从右向左滑动，切换到下一屏，将该屏幕的播放时间，设置为5分钟（也就是如果5分钟没有操作.则继续轮播）
			loginfo("当前播放的索引=" + cScreenObj.index)
			if (_queueRolling.length <= 1) {
				return;
			}
			if (cScreenObj.index < (_queueRolling.length - 1)) {
				var nextIndex = cScreenObj.index + 1;
				loginfo("播放下一个=" + nextIndex)
				startPlay(nextIndex);
			} else {
				loginfo("从头开始播放")
				startPlay(0);
			}
			cScreenObj.duration = delayed;
		} else if (msg['direction'] == 4) {
			//用户在从左向右滑动，切换到下一屏，将该屏幕的播放时间，设置为5分钟（也就是如果5分钟没有操作.则继续轮播）
			loginfo("当前播放的索引=" + cScreenObj.index)
			if (_queueRolling.length <= 1) {
				return;
			}
			if (cScreenObj.index > 0) {
				var nextIndex = cScreenObj.index - 1;
				loginfo("播放下一个=" + nextIndex)
				startPlay(nextIndex);
			} else {
				loginfo("从头开始播放")
				startPlay((_queueRolling.length - 1));
			}
			cScreenObj.duration = delayed;
		} else if (msg['direction'] == 0) {
			//用户没有滑动，但是有点击屏幕，将当前播放的屏幕播放时间延长，同时显示导航按钮
			cScreenObj.duration = delayed;
			cScreenObj.playtime = 0; //秒 ， 重新记录播放时长
			cScreenObj.starttime = new Date().getTime(); //毫秒 从新设置开始时间
			sendSuspensionNavWindowEvent({"op":1});
		} else if (msg['direction'] == -1) {
			//从导航选择了指定的屏幕
		} else if (msg['direction'] == -2) {
			//滑动导航
			cScreenObj.playtime = 0; //秒
			cScreenObj.starttime = new Date().getTime(); //毫秒
			cScreenObj.duration = delayed;
		} else if (msg['direction'] == -3) {
			//长按
		} else if (msg['direction'] == -4) {
			//回到第一個大屏
			startPlay((_queueRolling.length - 1));
		}

		
	}
	function playContentList() {
		//loginfo("time=" + new Date().getTime() + ";cScreenObj.duration=" + cScreenObj.duration);
		//获取当前播放的对象，索引、播放时长，定时切换到下一个，或者启动指定时间需要启动的内容。
		var now = new Date().getTime(); //毫秒
		var t = now / 1000 - cScreenObj.starttime / 1000;

		//检查有无到时间需要播放的内容
		if (_queueFixedtime[timefmt('HH:mm')]) {
			loginfo(_queueFixedtime[timefmt('HH:mm')])
			startPlayRolling(_queueFixedtime[timefmt('HH:mm')])
		} else if (_queueFixedtime[timefmt('YYYY-MM-DD HH:mm')]) {
			loginfo(_queueFixedtime[timefmt('YYYY-MM-DD HH:mm')])
			startPlayRolling(_queueFixedtime[timefmt('YYYY-MM-DD HH:mm')])
		} else {
			if (cScreenObjFixedtime.winid) {
				//说明有定时任务在播放，检查是否已满足设定的播放时间
				var t1 = now / 1000 - cScreenObjFixedtime.starttime / 1000;
				if (t < cScreenObjFixedtime.duration) {
					//继续播放定时任务
					return;
				} else {
					cScreenObjFixedtime.winid = null;
					cScreenObj.duration = 0; //设置播放时间为0，方便后面快速切换下一内容
				}
			}
			if (t >= cScreenObj.duration) {
				loginfo("当前播放的索引=" + cScreenObj.index)
				if (_queueRolling.length == 1) {
					return;
				}
				if (cScreenObj.index < (_queueRolling.length - 1)) {
					var nextIndex = cScreenObj.index + 1;
					loginfo("播放下一个=" + nextIndex)
					startPlay(nextIndex);
				} else {
					loginfo("从头开始播放")
					startPlay(0);
				}
				//自动轮播时,隐藏导航,2 表示关闭整改导航，包括按钮和 缩略图窗口
				showHideSuspensionNavWindow({"op":2});
			}
		}
	}

	/**
	 * step1，接收到消息，加载所需要展示的页面。
	 * 
	 * @param {} msg 
	 */
	function loadContentPage(msg) {
		loginfo(msg)
		//客户端加载的配置信息呈现
		showHideSuspensionNavWindow({"op":0})
		//loginfo(runDebugMode)
		appConfig._contentMode = 1;//
		createScreens(msg);
	}
}
